/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.pkw.server;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import pl.pkw.common.Card;
import pl.pkw.common.Tool;
import pl.pkw.common.Vote;
import pl.pkw.common.VotingData;

/**
 *
 * @author Agnieszka
 */
public class ServerTool extends Tool {

    private BigInteger n;
    private BigInteger e;
    private BigInteger d;
    private VotingData clientVotingData;
    Random generator = new Random(19580427);

    public ServerTool() {
        try {
            RSAPublicKey pubKey;
            RSAPrivateKey privKey;
            //generate the RSA key pair
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            //initialise the KeyGenerator with a random number.
            keyGen.initialize(1024, new SecureRandom());
            KeyPair keypair = keyGen.genKeyPair();
            privKey = (RSAPrivateKey) keypair.getPrivate();
            pubKey = (RSAPublicKey) keypair.getPublic();

            e = pubKey.getPublicExponent();
            d = privKey.getPrivateExponent();
            n = pubKey.getModulus();
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(ServerTool.class.getName()).log(Level.SEVERE, null, ex);

        }
    }

    /**
     * 
     * @return  skipped card number
     */
    public Integer randomCard() {
        Integer g = generator.nextInt(clientVotingData.getCards().size());

        Card card = clientVotingData.getCards().get(g.intValue());

        System.out.println("random card " + g + " " + card.getNumber() + " size " + clientVotingData.getCards().size());

        return card.getNumber();
    }

    public Boolean verifyBlind(VotingData votingData) throws UnsupportedEncodingException {
        clientVotingData = votingData;

        for (Card c : clientVotingData.getCards()) {
            System.out.println("card " + c.getNumber());
            String first = null;
            for (Vote v : c.getVotes()) {
                if (first == null) {
                    first = new String(Tool.unblindToClean(v.getBlindVote(), e, n, c.getR()).toByteArray()).split(";")[1];
                } else {
                    String next = new String(Tool.unblindToClean(v.getBlindVote(), e, n, c.getR()).toByteArray()).split(";")[1];
                    if (!first.equals(next)) {
                        return Boolean.FALSE;
                    }
                }

            }

        }


        return Boolean.TRUE;
    }

    public Card signCard() throws UnsupportedEncodingException {
        for (Vote v : clientVotingData.getSkipCard().getVotes()) {
            v.setBlindSignVote(Tool.sign(v.getBlindVote(), d, n));
        }

        return clientVotingData.getSkipCard();
    }

    public void verifyVote(Vote signVote) throws UnsupportedEncodingException {
        Tool.verify(signVote.getSignUnblindVote(), signVote.getHashVote(), d, n);

        Tool.verifyByRSA(signVote.getSignUnblindVote(), signVote.getHashVote(), e, n);
    }

    /**
     * 
     * @return  e - public key exponent
     */
    public BigInteger getE() {
        return e;
    }

    /**
     * 
     * @return n - public key modulus
     */
    public BigInteger getN() {
        return n;
    }

    public void setClientVotingData(VotingData clientVotingData) {
        this.clientVotingData = clientVotingData;
    }

    public BigInteger getD() {
        return this.d;
    }
}
